#ifndef __RING_BUF_H__
#define __RING_BUF_H__

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>

typedef struct ring_buf_t
{
    /* buf起始地址 */
    char* buffer;
    /* buf大小-1, 作为模算子 */
    uint32_t buffer_mask;
    /* 尾节点下标 */
    uint32_t tail_index;
    /* 头节点下标 */
    uint32_t head_index;
} ring_buf_t;

/**
 * @brief 判断ring_buf的空间是否为2^n, 
 * 设计原因, buf_size只能为2^n
 */
#define RING_BUFFER_IS_POWER_OF_TWO(buf_size) ((buf_size & (buf_size - 1)) == 0)

/**
 * @brief 返回模算子,用作取模运算中
 * a % b = a & (b-1) 仅限于 b = 2^n
 */
#define RING_BUFFER_MASK(rb) (rb->buffer_mask)

/**
 * @brief 判断buf是否为满
 * @param buffer buf句柄
 * @return 1 满;  0 未满.
 */
static inline uint8_t ring_buf_is_full(ring_buf_t* buffer)
{
    return ((buffer->head_index - buffer->tail_index) & RING_BUFFER_MASK(buffer)) == RING_BUFFER_MASK(buffer);
}

/**
 * @brief 判断buf是否为空
 * @param buffer buf句柄
 * @return 1 空;  0 未空.
 */
static inline uint8_t ring_buf_is_empty(ring_buf_t* buffer)
{
    return (buffer->head_index == buffer->tail_index);
}

/**
 * @brief 获取当前buf中数据数量
 * @param buffer buf句柄
 * @return 1 空;  0 未空.
 */
static inline uint32_t ring_buf_num_items(ring_buf_t* buffer)
{
    return ((buffer->head_index - buffer->tail_index) & RING_BUFFER_MASK(buffer));
}

/**
 * @brief 创建一块ring_buf
 * @param ring_buf : buf句柄
 * @param buf : buf首地址
 * @param buf_size : buf大小
 * @return 0 : buf_size不符合预期, buf_size = 2^n
 *         1 : 创建成功
 */
int ring_buf_init(ring_buf_t* ring_buf, char* buf, uint32_t buf_size);

/**
 * @brief 向buffer头部写入一个字符
 * @param buffer : buf句柄
 * @param data : 写入的数据
 * @return NULL
 */
void ring_buf_queue(ring_buf_t* buffer, char data);

/**
 * @brief 向buffer头部写入一串字符
 * @param buffer : buf句柄
 * @param arr : 写入数据的数组
 * @param arr_size : 数组的长度
 * @return NULL
 */
void ring_buf_queue_arr(ring_buf_t* buffer, const char* arr, uint32_t arr_size);

/**
 * @brief 从buffer尾部读取一个字符
 * @param buffer : buf句柄
 * @param data : 读取的数据
 * @return NULL
 */
int ring_buf_dequeue(ring_buf_t* buffer, char* data);

/**
 * @brief 从buffer尾部读取一串字符
 * @param buffer : buf句柄
 * @param arr : 接受数据的数组
 * @param arr_size : 数组的长度
 * @return 读取数据的大小
 */
uint32_t ring_buf_dequeue_arr(ring_buf_t* buffer, char* arr, uint32_t len);

/**
 * @brief 从buffer中读取index的数据
 * @param buffer : buf句柄
 * @param data : 接受数据
 * @param index : buf中的第几位数据
 * @return 0 : index超过了数据长度
 *         1 : 读取成功
 */
uint8_t ring_buf_peek(ring_buf_t* buffer, char* data, uint32_t index);

#ifdef __cplusplus
} /*extern "C"*/
#endif

#endif  /* __RING_BUF_H__ */
